package net.guerlab.smart.wx.api.autoconfig;

import lombok.AllArgsConstructor;
import net.guerlab.commons.collection.CollectionUtil;
import net.guerlab.smart.platform.commons.util.BeanConvertUtils;
import net.guerlab.smart.wx.api.WxUserApi;
import net.guerlab.smart.wx.core.domain.WxUserDTO;
import net.guerlab.smart.wx.core.exception.WxUserInvalidException;
import net.guerlab.smart.wx.core.searchparams.WxUserSearchParams;
import net.guerlab.smart.wx.service.entity.WxUser;
import net.guerlab.smart.wx.service.service.WxUserService;
import net.guerlab.web.result.ListObject;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.*;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.lang.NonNull;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author guer
 */
@Configuration
@Conditional(WxUserApiLocalServiceAutoConfigure.WrapperCondition.class)
public class WxUserApiLocalServiceAutoConfigure {

    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    @Bean
    @ConditionalOnBean(WxUserService.class)
    public WxUserApi wxUserApiLocalServiceWrapper(WxUserService service) {
        return new WxUserApiLocalServiceWrapper(service);
    }

    @SuppressWarnings("WeakerAccess")
    static class WrapperCondition implements Condition {

        @Override
        public boolean matches(@NonNull ConditionContext context, @NonNull AnnotatedTypeMetadata metadata) {
            try {
                return WrapperCondition.class.getClassLoader()
                        .loadClass("net.guerlab.smart.wx.service.service.WxUserService") != null;
            } catch (Exception e) {
                return false;
            }
        }
    }

    @AllArgsConstructor
    private static class WxUserApiLocalServiceWrapper implements WxUserApi {

        private final WxUserService service;

        @Override
        public WxUserDTO findOne(String appId, String openId) {
            WxUser wxUser = service.findUser(appId, openId);

            if (wxUser == null) {
                throw new WxUserInvalidException();
            }

            return wxUser.toDTO();
        }

        @Override
        public ListObject<WxUserDTO> findList(WxUserSearchParams searchParams) {
            return BeanConvertUtils.toListObject(service.selectPage(searchParams));
        }

        @Override
        public List<WxUserDTO> findAll(WxUserSearchParams searchParams) {
            return BeanConvertUtils.toList(service.selectAll(searchParams));
        }

        @Override
        public Map<String, WxUserDTO> findMap(Collection<String> openIds) {
            if (openIds == null || openIds.isEmpty()) {
                return Collections.emptyMap();
            }

            WxUserSearchParams searchParams = new WxUserSearchParams();
            searchParams.setOpenIds(openIds);

            Collection<WxUser> wxUsers = service.selectAll(searchParams);

            return CollectionUtil.toMap(wxUsers, WxUser::getOpenId, WxUser::toDTO);
        }

        @Override
        public int findCount(WxUserSearchParams searchParams) {
            return service.selectCount(searchParams);
        }
    }

}
